﻿// ==UserScript==
// @name			Ikariam TopList Data Collector
// @namespace		Ikariam-TopList-Data-Collector
// @description		Collects data from Ikariam toplist through embassy 
// @author			salomone
// @version			0.3.1
// @include			http://s*.ikariam.*/*view=embassy*
// ==/UserScript==
// History:
// v.0.1.0 - 19/10/2009
//	* first commited
//	* puts a button on embassy page, after hitting it, it will collect and display the name of the alliance members (hard coded to first 10 rows only now)
// v.0.2.0 - 28/10/2009
//	* get all of the needed data
//	* describes maximum values for score and army score, calculate percentages
//	* put everything in the textarea, formatted for csv output
// v.0.2.1 - 13/11/2009
//	* output list descending ordered by second column (average score) 
// v.0.2.2 - 20/11/2009
//	* fixed some bugs caused by player names
// v.0.3.0 - 21/11/2009
//	* top list selector checkboxes
//	* temporaly removed percentage average counting
//	* temporaly removed ordering
// v.0.3.1 - 13/12/2009
//	* fixed first four columns : playerid;playername;allianceid;alliancename
//	* colum names added by selected top lists 
//	* added dbmode switch variable

$ = document.getElementById;
var gameServer = top.location.host;
var url = self.location.href;

var memberListTable = null;

var memberPoints = new Object();

var trimEverythingExceptNumbers = new RegExp('[\\D]', 'g');
var SCOREPOINTS = "_POINTS";
var MAXPOINT = "_MAXPOINT";
var PROCESSEDPOINTS = "_PROCESSEDPOINTS";
var NUMBER_OF_ALLIANCE_MEMBERS = "numberOfAlliaceMembers";

var globalSorterIdx = 2; 

// Ha ezt bekapcsolod, akkor csak az első 10 embert szedi össze
var shortenedList = false;
var checkBoxes = null;
var selectedCheckBoxes = new Array();
var scorePointTypesToProcess = 0;

// Ez állítható lesz felületről, ez vezérli hogy emberi formájú kimenetet szeretnénk vagy majd elküldjük a php felé az adatokat.
var dbmode = true;

function getGM_Value( variableName )	{
	return GM_getValue ( variableName );
}

function setGM_Value ( variableName, variableValue )	{
	GM_setValue ( variableName, variableValue );
}

function initCheckBoxesForScoreTypes()	{
	var res = new Object();
	res['score'] = 'Összes pontok';
	res['building_score_main'] = 'Mesteri építők';
	res['building_score_secondary'] = 'Épület szintek';
	res['research_score_main'] = 'Tudósok';
	res['research_score_secondary'] = 'Fejlesztés szintjei';
	res['army_score_main'] = 'Tábornokok';
	res['trader_score_secondary'] = 'Arany készlet';
	res['offense'] = 'Támadó pontok';
	res['defense'] = 'Védelmi pontok';
	res['trade'] = 'Toplista kereskedelem';
	return res;
}

if ( url.indexOf('view=embassy') > 0  )	{		
	checkBoxes = initCheckBoxesForScoreTypes();
	memberListTable = getMemberListTable();	
	putButton();
}

function addEvent(obj, evType, fn, bubble)	{
	if (obj.addEventListener)	{
		obj.addEventListener(evType, fn, bubble);
		return true;
	} 
	else if (obj.attachEvent)	{
		var r = obj.attachEvent('on'+evType, fn);
		return r;
	}
	else	{
		return false;
	}
}

function $x( xpath, root ) {
  var doc = root ? root.evaluate ? root : root.ownerDocument : document, next;
  var got = doc.evaluate( xpath, root||doc, null, 0, null ), result = [];
  switch (got.resultType) {
    case got.STRING_TYPE:
      return got.stringValue;
    case got.NUMBER_TYPE:
      return got.numberValue;
    case got.BOOLEAN_TYPE:
      return got.booleanValue;
    default:
      while (next = got.iterateNext())
        result.push( next );
      return result;
  }
}

function $X( xpath, root ) {
	  var got = $x( xpath, root );
	  return got instanceof Array ? got[0] : got;
}

function getMemberListTable()	{
	var mainView = $X(".//div[@id='mainview']");
	var contentDiv = $x("./div[@class='contentBox01h']", mainView)[1];	
	return $X("./div[@class='content']/table[@id='memberList']", contentDiv);
}

function getMemberListRows(memberListTable)	{	
	return $x("./tbody/tr", memberListTable);
}

function getMemberNameFromRow(memberListRow)	{
	return $X("./td[position() = 2 ]", memberListRow).firstChild.nodeValue;
}

function getContextBoxRoot(page)	{
	if (page)	{
		return $X(".//div[@id='mainview']/div[@class='contentBox01h']", page);
	}
	
	return $X(".//div[@id='mainview']/div[@class='contentBox01h']");
}

function createCheckBoxesTableRows()	{
	var res = new Array();
	
	var tr = null;
	var td = null;
	var cb = null;
	var i = '';
	for ( i in checkBoxes )	{
		tr = document.createElement('tr');		
		td = document.createElement('td');
		cb = document.createElement('input');
		td = document.createElement('td');		
		td.appendChild( document.createTextNode( checkBoxes[i] ) );		
		tr.appendChild(td);		
		cb.setAttribute('type', 'checkbox');
		cb.setAttribute('id', i);
		td = document.createElement('td');
		td.appendChild(cb);
		tr.appendChild(td);		
		res.push(tr);
	}
	return res;
}

function getMarkedCheckBoxes()	{
	var rootForButtonRow = null;	
	rootForButtonRow =$X(".//div[@id='mainview']/div[@class='contentBox01h']/div[@class='content']/table/tbody"); 
	var checkBoxes = $x("./tr/td/input", rootForButtonRow );
	var i = null;
	for ( i in checkBoxes )	{	
		if ( checkBoxes[i].checked )	{
			selectedCheckBoxes.push( checkBoxes[i].getAttribute('id') );
			scorePointTypesToProcess++;
		}
	}
	
}

function putButton()	{	
	var startButton = null;
	startButton = document.createElement('input');
	startButton.setAttribute('type', 'button');
	startButton.setAttribute('id', 'extendTradeAdvisorSaveButton');
	startButton.setAttribute('value', 'Start' );
	startButton.setAttribute('class', 'button' );
	
	addEvent( startButton, 'click', function(){startDataCollect();}, true );		
	
	var rootForButtonRow = null;	
	rootForButtonRow =$X(".//div[@id='mainview']/div[@class='contentBox01h']/div[@class='content']/table/tbody");	
	
	var trForButton = null;
	trForButton = document.createElement('tr');
	
	var tdForButton = null;
	tdForButton = document.createElement('td');	
	tdForButton.setAttribute('class', 'desc');
	
	tdForButton.appendChild( startButton );
	trForButton.appendChild( tdForButton );
	
	var myCheckBoxes = createCheckBoxesTableRows();
	var i = null;
	for ( i in myCheckBoxes )	{
		rootForButtonRow.appendChild( myCheckBoxes[i] );
	}
	
	rootForButtonRow.appendChild( trForButton );
}

function startDataCollect()	{
	
	getMarkedCheckBoxes();
	
	if ( scorePointTypesToProcess == 0 )	{
		alert ( "Nem választottál ki semmit!");
		return;
	}
	
	resetCollectedData();	
	
	var memberRows = getMemberListRows( memberListTable );
	var c = memberRows.length;
	
	var i = 0;
	var j = null;
	var memberName = '';
	
	// TODO -- HARD CODE a rövidebb futásidő érdekében. Ha a ciklusban az első 10 emberre elvégzi a feldolgozást helyesen, akkor mindenkire is el fogja végezni..
	if ( shortenedList ) {
		c = 10;
	}
	
	setGM_Value(NUMBER_OF_ALLIANCE_MEMBERS, c);
	
	for ( i = 0; i != c; i++ )	{		
		memberName = getMemberNameFromRow( memberRows[i] );
		for ( j in selectedCheckBoxes )	{
			requestPlayerScores(memberName, getHighScoreData, selectedCheckBoxes[j]);
		}
	}
	return ;
}

function resetCollectedData()	{
	var i = null;
	for ( i in selectedCheckBoxes )	{
		setGM_Value( selectedCheckBoxes[i] + SCOREPOINTS, "" );
		setGM_Value( selectedCheckBoxes[i] + MAXPOINT, 0 );
		setGM_Value( selectedCheckBoxes[i] + PROCESSEDPOINTS, 0 );
		setGM_Value( "playerIdListString", "" );
	}
}

function requestPlayerScores(playerName, fn, scoreType) {
    GM_xmlhttpRequest({
        method:'POST',
        url:'http://' + gameServer + '/index.php',
        data:'view=highscore&highscoreType=' + scoreType + '&searchUser=' + playerName,
        headers: {
            'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
            'Content-type': 'application/x-www-form-urlencoded',
            'Accept': 'application/atom+xml,application/xml,text/xml',
            'Referer': 'http://' + gameServer + '/index.php',
            'Cookie': document.cookie
        },
        onload:function(xhr) { fn(xhr.responseText); }
    } );
}

function getHighScoreData(page)	{	
	
	if ( page )	{
		
		var contentDiv = $X(".//*[@id='mainview']/div[@class='contentBox01h']/div[@class='content']", createHiddenDiv('hidden_score_div_id', page));			
		var playerName = new String( $X("./table[@class='table01']/tbody/tr/td[position() = 2]/td/input[@name='searchUser']", contentDiv ).value );		
		
		var nameCells = $x("./table[@class='table01' and position()=2]/tbody/tr[@class]/td[@class='name']", contentDiv );
		var processedCell = getProcessedNameCell( nameCells, playerName );
		
		var playerIdListString = "";
		playerIdListString = getGM_Value( "playerIdListString" );
		
		if ( ! (playerIdListString.indexOf(playerName) > -1 ) && processedCell != null)	{
			var playerAllyLink = $X("./../td[@class='allytag']/a", processedCell );
			var playerLink = $X("./../td[@class='action']/a", processedCell );
			
			var allyIdString = "0";
			var allyName = "N/A";
			var playerIdString = "0";
			
			
			if ( playerAllyLink != null )	{
				var stringAfterAllyId = playerAllyLink.href.split('&allyId=')[1];
				allyIdString = stringAfterAllyId.split('&')[0];	
				allyName = allyIdString == "0" 
					? 'N/A' 
					: playerAllyLink.innerHTML;
			}
			
			
			if ( playerLink != null )	{
				var stringAfterplayerId = playerLink.href.split('&receiverId=')[1];
				playerIdString = stringAfterplayerId.split('&')[0];			
			}
			
			playerIdListString += '##' + playerName + '=' + playerIdString + ';' + allyIdString + ';' + allyName;			
			setGM_Value( "playerIdListString", playerIdListString );
		}
		
		
		var highScoreStr = processedCell == null ? "0" : new String($X("./../td[@class='score']", processedCell ).innerHTML );
		var highScore = parseInt ( highScoreStr.replace(trimEverythingExceptNumbers, "") );
		
		var scoreType = getActualHighScorePageType( contentDiv );
	
		var highScores = "";
		highScores = getGM_Value( scoreType + SCOREPOINTS ) ;
		if ( highScores == null )	{
			highScores = "";
		}
		highScores = highScores + ("##"+playerName+"#"+highScore);
		setGM_Value( scoreType + SCOREPOINTS, highScores );
		
		var maxScore = parseInt( getGM_Value( scoreType + MAXPOINT ) );
		if ( highScore > maxScore ) {
			setGM_Value( scoreType + MAXPOINT, highScore );
		}
		
		var numberOfProcessedScores = parseInt( getGM_Value( scoreType + PROCESSEDPOINTS ) ) + 1;		
		setGM_Value( scoreType + PROCESSEDPOINTS, numberOfProcessedScores );
		
		checkIsAllScoresProcessed();
	}
}

function getActualHighScorePageType( page )	{	
	var optionList = null;
	optionList = document.createElement('select');
	optionList = $X("./table[@class='table01']/tbody/tr/td[position() = 2]/form/div/select", page ) ;
	
	var options = null;
	options = new Array();
	options = $x("./option", optionList);
	
	var selectedOption = null;
	selectedOption = document.createElement('option');	 
	selectedOption = options[optionList.selectedIndex];
	return selectedOption.value;
}

function checkIsAllScoresProcessed()	{
	var numOfMembers = parseInt( getGM_Value(NUMBER_OF_ALLIANCE_MEMBERS) );
	
	var processedScorePoints = 0;
	var i = null;
	for ( i in selectedCheckBoxes )	{
		processedScorePoints += parseInt( getGM_Value( (selectedCheckBoxes[i] + PROCESSEDPOINTS) ) ); 
	}	
	
	if ( ( numOfMembers * scorePointTypesToProcess ) == processedScorePoints  ) {
		updateScoreDate( numOfMembers );
	}
}

function updateScoreDate(numOfMembers)	{
	var memberDataBox = null;
	memberDataBox = document.createElement('textarea');
	memberDataBox.setAttribute('rows', numOfMembers);
	memberDataBox.setAttribute('cols', 100);
	
	var rootForMemberDataBox = null;	
	rootForMemberDataBox = document.createElement('table');
	rootForMemberDataBox =$X(".//div[@id='mainview']/div[@class='contentBox01h']/div[@class='content']/table"); 
	
	var trForMemberDataBox = null;
	trForMemberDataBox = document.createElement('tr');
	
	var tdForMemberDataBox = null;
	tdForMemberDataBox = document.createElement('td');	
	tdForMemberDataBox.setAttribute('class', 'desc');
	tdForMemberDataBox.setAttribute('colspan', '2');
	
	tdForMemberDataBox.appendChild( memberDataBox );
	trForMemberDataBox.appendChild( tdForMemberDataBox );
	rootForMemberDataBox.appendChild( trForMemberDataBox );
	
	if ( dbmode )	{
		createOutputInDbFormat( memberDataBox );
	}
	else	{
		createOutputInHumanReadableFormat( memberDataBox );
	}	
}

function createOutputInDbFormat( memberDataBox )	{
	var highScores = new Object();
	var actualHighScores = new Object();
	var memberScores = null;
	
	var memberName = "";
	var currentRow = "";
	var i = null;
	
	var padderStringForNotFoundMembers = '-1;-1;N/A';
	
	var playerDatas = new Object();
	playerDatas = convertStringToObject( "##", "=", getGM_Value( "playerIdListString" ) );
	
	for ( i in selectedCheckBoxes )	{			
		actualHighScores = new Object();
		actualHighScores = convertStringToObject( "##", "#", getGM_Value( selectedCheckBoxes[i] + SCOREPOINTS ) );
		
		for ( memberName in actualHighScores )	{			
			memberScores = highScores[memberName] == null ? new Object() : highScores[memberName];			
			memberScores[ selectedCheckBoxes[i] ] = actualHighScores[memberName];
			highScores[memberName] = memberScores;
		}		 
	}

	currentRow = "playername;playerid;allianceid;alliancename";
	for ( i in selectedCheckBoxes )	{
		currentRow += ";" + selectedCheckBoxes[i];
	}	
	currentRow += "###";
	
	for ( memberName in highScores )	{		
		currentRow += "\n" + memberName + ';' + ( playerDatas[memberName] == null  || playerDatas[memberName] == undefined ? padderStringForNotFoundMembers : playerDatas[memberName] ) ;
		for ( i in selectedCheckBoxes )	{
			memberScores = highScores[memberName];			
			currentRow += ";" + memberScores[ selectedCheckBoxes[i] ];
		}		
		currentRow += "##";
	}	
	
	memberDataBox.appendChild( document.createTextNode( currentRow.substring(0,  currentRow.lastIndexOf('##') ) ) );
}

function createOutputInHumanReadableFormat( memberDataBox )	{

	var highScores = new Object();
	var actualHighScores = new Object();
	var maxScore = 0;
	var memberScores = null;
	
	var memberName = "";
	var currentRow = "";
	var currentScore = 0;
	var currentScorePercentage = 0.0;
	var currentScorePercentageStr = 0.0;
	var i = null;
	
	for ( i in selectedCheckBoxes )	{			
		actualHighScores = new Object();
		actualHighScores = convertStringToObject( "##", "#", getGM_Value( selectedCheckBoxes[i] + SCOREPOINTS ) );
		maxScore = parseInt( getGM_Value( selectedCheckBoxes[i] + MAXPOINT ) );
		
		for ( memberName in actualHighScores )	{
			currentScore = parseInt( actualHighScores[memberName] );
			currentScorePercentage = currentScore / maxScore;
			memberScores = highScores[memberName] == null ? new Object() : highScores[memberName];			
			memberScores[ selectedCheckBoxes[i] ] = currentScore + ";" + currentScorePercentage;
			highScores[memberName] = memberScores;
		}		 
	}
	
//	scores.sort( sortMultidimensioanlArrayCaseInSensitiveByGlobalSorterIdxDescending );

	currentRow = "Név";
	for ( i in selectedCheckBoxes )	{
		currentRow += ";" + checkBoxes[ selectedCheckBoxes[i] ] + ";" +  checkBoxes[ selectedCheckBoxes[i] ] + " %";
	}	
	
	for ( memberName in highScores )	{
		currentRow += "\n" + memberName;
		for ( i in selectedCheckBoxes )	{
			memberScores = highScores[memberName];			
			currentRow += ";" + memberScores[ selectedCheckBoxes[i] ];
		}		
	}
	
	memberDataBox.appendChild( document.createTextNode( currentRow ) );
}

function createHiddenDiv( divId, divContent )	{
	var hiddenDiv = document.createElement('div');
	hiddenDiv.style.display = 'none';
	hiddenDiv.style.visibility = 'hidden';
	hiddenDiv.id = 'undefined' == divId || null == divId ? 'hiddenDiv' + ( Math.random() * 100 ) : divId ;
	
	if (divContent)	{
		hiddenDiv.innerHTML = 'string' == typeof divContent ? divContent : divContent.toXMLString();
	}
	
	return hiddenDiv;
}

function convertStringToObject(mainSeparator, subSeparetor, sourceString)	{
	var pairs = sourceString.replace("##","").split( mainSeparator );
	var pair = "";
	var res = new Object();
	var elements = "";
	for ( pair in pairs )	{
		elements = pairs[pair].split(subSeparetor);
		res[elements[0]] = elements[1];
	}
	return res;
}

function getProcessedNameCell(nameCellList, playerName)	{
	var i = 0;	
	var found = false;
	try	{
		while ( !found && i != nameCellList.lenght )	{		
			if ( nameCellList[i].innerHTML == playerName )	{
				found = true;
			}
			else	{
				i++;
			}		
		}
	}
	catch ( err )	{
		return null;
	}
	return found ? nameCellList[i] : null;
}

function sortMultidimensioanlArrayCaseInSensitiveByGlobalSorterIdxAscending(a, b)	{
	return sortMultidimensioanlArrayCaseInSensitive(a, b, globalSorterIdx, true);
}

function sortMultidimensioanlArrayCaseInSensitiveByGlobalSorterIdxDescending(a, b)	{
	return sortMultidimensioanlArrayCaseInSensitive(a, b, globalSorterIdx, false);
}

function sortMultidimensioanlArrayCaseInSensitiveAndDescending(a, b, idx)	{
	return sortMultidimensionalArray(a, b, idx, false, false);
}

function sortMultidimensioanlArrayCaseInSensitive(a, b, idx)	{
	return sortMultidimensionalArray(a, b, idx, false, true);
}

function sortMultidimensionalArray(a, b, idx, caseInSensitive, ascending)    {	
    if ( idx == null || idx == 'undefined' )    {
        idx = 0;
    }
    
    var orientationOfSorting = new Array(2);
    if ( !ascending )	{
    	orientationOfSorting[0] = 1;
    	orientationOfSorting[1] = -1;
    }
    else	{
    	orientationOfSorting[0] = -1;
    	orientationOfSorting[1] = 1;
    }
    
    return caseInSensitive 
    ? ( ( a[idx].toUpperCase() < b[idx].toUpperCase() ) ? orientationOfSorting[0] : orientationOfSorting[1] )
    : ( ( a[idx] < b[idx] ) ? orientationOfSorting[0] : orientationOfSorting[1] );
}